<!doctype html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="chrome=1"/>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>Voronoi test</title>
    <script src="../webapp/cnc/maths/morphology.js"></script>
    <script src="../webapp/libs/require.js"></script>
    <script src="../webapp/config.js"></script>
    <script>
        requirejs.config({
            baseUrl: '../webapp'
        });
    </script>
    <link rel="shortcut icon" href="../webapp/images/icon_fraise_48.png"/>
    <style>
        * {
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
            box-sizing: border-box;
        }

        th {
            text-align: right;
        }
    </style>
</head>
<body>
<div id="drawing" style="width:512px; height: 512px; float:left;">

</div>
<canvas id="depth" width="512" height="512"
        style="background-color: #000000;border:solid; float:right; position: relative">
</canvas>
<script>

    require(['jQuery', 'THREE', 'RSVP', 'libs/threejs/postprocessing/ShaderPass', 'libs/svg', 'cnc/cam/cam',
                'shader!default_vUv.vert', 'shader!distance.frag', 'shader!medial_axis.frag',
                'shader!max_value.frag', 'shader!median.frag', 'shader!reconstruction_from_ma.frag',
                'shader!/polyborder.frag'],
            function ($, THREE, RSVP, ShaderPass, SVG, cam, defaultVUvShader, distanceShader, medialAxisShader, maxFragmentShader,
                      medianFragmentShader, reconstructionShader, polyBorderShader) {
                var vWidth = 512;
                var vHeight = 512;
                //this pass receives a float texture named 'points' where the X is encoded in luminance and Y is in alpha
                //it generates a map of the square distance field of all the segments scaled by textureScale or distanceScale
                var distancePass = new ShaderPass({
                    uniforms: {
                        points: {type: 't', value: null},
                        textureScale: {type: 't', value: null},
                        distanceScale: {type: 'f', value: 1},
                        gridSize: {type: 'v2', value: new THREE.Vector2(vWidth, vHeight)},
                        projectionMatrix2: {type: 'm4'},
                        viewMatrix2: {type: 'm4'}
                    },
                    defines: {
                        pointCount: 10
                    },
                    vertexShader: defaultVUvShader,
                    fragmentShader: distanceShader
                }, 'points');

                //this pass receives a 'modelHeight' texture and rasterize the ridges on it, the rest being blank
                var medialAxisPass = new ShaderPass({
                    defines: {
                        radialSamples: null
                    },
                    uniforms: {
                        modelHeight: {type: 't'},
                        toolToPartRatio: {type: 'v2', value: null},
                        terrainRatio: {type: 'v2', value: null},
                        gridSize: {type: 'v2', value: new THREE.Vector2(vWidth, vHeight)}
                    },
                    vertexShader: defaultVUvShader,
                    fragmentShader: medialAxisShader
                }, 'modelHeight');

                //receives a modelHeight and returns the max of the texture.
                //need only to be called on one fragment, it will sample the whole modelHeight in for each fragment
                //the result will be multiplied by scale
                var maxPass = new ShaderPass({
                    defines: {
                        gridX: null,
                        gridY: null
                    },
                    uniforms: {
                        modelHeight: {type: 't'},
                        scale: {type: 'f', value: 1}
                    },
                    vertexShader: defaultVUvShader,
                    fragmentShader: maxFragmentShader
                }, 'modelHeight');
                var medianPass = new ShaderPass({
                    defines: {
                        gridX: null,
                        gridY: null
                    },
                    uniforms: {
                        modelHeight: {type: 't'}
                    },
                    vertexShader: defaultVUvShader,
                    fragmentShader: medianFragmentShader
                }, 'modelHeight');
                var reconstructionPass = new ShaderPass({
                    defines: {
                        gridX: null,
                        gridY: null
                    },
                    uniforms: {
                        modelHeight: {type: 't'}
                    },
                    vertexShader: defaultVUvShader,
                    fragmentShader: reconstructionShader
                }, 'modelHeight');
                var borderPass = new ShaderPass({
                    uniforms: {
                        points: {type: 't', value: null},
                        gridSize: {type: 'v2', value: new THREE.Vector2(vWidth, vHeight)},
                        projectionMatrix2: {type: 'm4'},
                        viewMatrix2: {type: 'm4'}
                    },
                    defines: {
                        pointCount: 10
                    },
                    vertexShader: defaultVUvShader,
                    fragmentShader: polyBorderShader
                }, 'points');
                //stolen there: http://www.clker.com/inc/svgedit/svg-editor.html?paramurl=/inc/clean.html?id=162595
                var puzzle = 'M232.64845275878906,52.628318786621094 C216.02122497558594,53.22764205932617 197.37046813964844,58.68354797363281 187.4209747314453,70.36833953857422 C172.94898986816406,100.56008911132812 208.10482788085938,86.6199722290039 212.23968505859375,107.52195739746094 C216.37452697753906,128.42393493652344 191.5574188232422,129.579833984375 191.5574188232422,129.579833984375 L191.5574188232422,129.579833984375 L84.6250228881836,129.579833984375 C84.6250228881836,129.579833984375 84.76176452636719,233.40914916992188 84.76176452636719,233.4091339111328 C84.76176452636719,233.4091339111328 85.94230651855469,257.7080383300781 107.2900390625,253.65953063964844 C124.63508605957031,250.3701171875 118.48403930664062,227.0127716064453 132.10874938964844,225.97840881347656 C135.25291442871094,225.73971557617188 139.45431518554688,226.7022247314453 145.2360076904297,229.3590545654297 C157.16998291015625,239.10079956054688 162.74224853515625,257.36212158203125 163.35433959960938,273.64215087890625 C163.58030700683594,279.65203857421875 163.04443359375,285.3041687011719 161.98692321777344,290.244140625 C161.95977783203125,290.4633483886719 161.91331481933594,290.69415283203125 161.88436889648438,290.91357421875 C160.03134155273438,304.9603576660156 154.4873809814453,319.20953369140625 144.41554260253906,327.43121337890625 C113.5799331665039,341.6010437011719 127.81732940673828,307.17926025390625 106.46958923339844,303.1307373046875 C90.91576385498047,300.1810302734375 86.11091613769531,312.21185302734375 84.6250228881836,318.996337890625 L84.6250228881836,429.21875 C84.6250228881836,429.21875 191.93348693847656,428.3819580078125 191.9334716796875,428.3819580078125 C191.9334716796875,428.3819580078125 216.7505645751953,427.2260437011719 212.61572265625,406.3240966796875 C208.4808807373047,385.4220886230469 173.3592071533203,399.3621826171875 187.83119201660156,369.17047119140625 C197.78070068359375,357.48565673828125 216.3972625732422,352.02978515625 233.0244903564453,351.4304504394531 C239.16253662109375,351.2091979980469 244.9352264404297,351.73388671875 249.98052978515625,352.7693176269531 C250.20443725585938,352.7958984375 250.44017028808594,352.8414001464844 250.66424560546875,352.8697204589844 C265.0105895996094,354.68408203125 279.5978698730469,360.11224365234375 287.994873046875,369.9737854003906 C302.46685791015625,400.1655578613281 267.3110046386719,386.2254333496094 263.1761474609375,407.1274108886719 C259.0412902832031,428.0293884277344 283.8583984375,429.1852722167969 283.8583984375,429.1852722167969 L390.17547607421875,429.21875 L390.17547607421875,319.8666076660156 C391.692138671875,313.0628967285156 396.5233154296875,301.16900634765625 411.9858703613281,304.1014099121094 C433.3335876464844,308.1499328613281 419.09619140625,342.57171630859375 449.93182373046875,328.4018859863281 C460.0036315917969,320.18023681640625 465.547607421875,305.8975524902344 467.400634765625,291.85076904296875 C467.4295654296875,291.6313781738281 467.4760437011719,291.4340515136719 467.5032043457031,291.2148132324219 C468.5606689453125,286.27484130859375 469.0965881347656,280.6227111816406 468.87060546875,274.6128234863281 C468.2585144042969,258.3327941894531 462.686279296875,240.07147216796875 450.75225830078125,230.32972717285156 C419.9166259765625,216.15992736816406 434.154052734375,250.58169555664062 412.8063049316406,254.6302032470703 C391.45855712890625,258.6787414550781 390.2780456542969,234.3798065185547 390.2780456542969,234.3798065185547 L390.17547607421875,129.579833984375 L278.42291259765625,129.579833984375 C271.4156188964844,127.9925308227539 259.8650817871094,123.16194915771484 262.80010986328125,108.32527923583984 C266.9349670410156,87.42329406738281 302.056640625,101.36341094970703 287.5846252441406,71.17166137695312 C279.1876220703125,61.31014633178711 264.6345520019531,55.8819580078125 250.28819274902344,54.067604064941406 C250.06411743164062,54.03927230834961 249.82839965820312,53.9937629699707 249.6044921875,53.96718978881836 C244.55918884277344,52.9317626953125 238.7864990234375,52.40707778930664 232.64845275878906,52.628318786621094 z';
                //var puzzle = "M235.12163,288.70404c-0.4189,-69.36761 65.69643,-125.90895 147.73921,-126.34552c82.04279,-0.43655 148.83673,55.39758 149.25568,124.76517c0.41895,69.36761 -65.69641,125.90894 -147.7392,126.34552c-82.04279,0.43655 -148.83678,-55.39758 -149.25569,-124.76517z"
                //var puzzle = 'M100, 100L100,300L550, 300L550, 200L250, 200L250,100z';

                function hyp(x, y) {
                    return Math.sqrt(x * x + y * y);
                }

                var paper = SVG($('#drawing')[0]).size(512, 512);
                paper.viewbox(0, 0, 512, 512);
                var group = paper.group();

                var puzzleTranslation = {x: -70, y: -55};
                var puzzlePath = group.path(puzzle, true).translate(puzzleTranslation.x, puzzleTranslation.y);
                puzzlePath.attr({fill: 'none', stroke: '#000000', 'stroke-width': 3});
                var points = cam.pathDefToPolygons(puzzle)[0];
                var graphRenderer = new THREE.WebGLRenderer({
                    antialias: false,
                    alpha: false,
                    devicePixelRatio: 1,
                    canvas: $('#depth')[0],
                    stencil: false,
                    preserveDrawingBuffer: true
                });
                var renderTargetWidth = 300;
                var renderTargetHeight = 300;
                var colorDepthTexture = new THREE.Texture(undefined, THREE.Texture.DEFAULT_MAPPING,
                        THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter, THREE.NearestFilter,
                        THREE.RGBAFormat, THREE.FloatType);
                colorDepthTexture.generateMipmaps = false;

                var depthRT = new THREE.WebGLRenderTarget(renderTargetWidth, renderTargetHeight, {
                            stencilBuffer: false, texture: colorDepthTexture
                        }
                );
                depthRT.generateMipmaps = false;
                var depthRT2 = depthRT.clone();
                var maxTexture = new THREE.DataTexture(new Float32Array([1.0, 0.0, 0.0, 0.0]), 1, 1, THREE.RGBAFormat, THREE.FloatType,
                        THREE.Texture.DEFAULT_MAPPING, THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter, THREE.NearestFilter);
                maxTexture.generateMipmaps = false;
                var maxRT = new THREE.WebGLRenderTarget(1, 1, {
                            stencilBuffer: false, texture: maxTexture
                        }
                );
                maxRT.generateMipmaps = false;
                graphRenderer.autoClear = false;
                graphRenderer.setSize(vWidth, vHeight);
                var puzzleBBOX = puzzlePath.node.getBBox();
                var bboxBiggestDim = Math.max(puzzleBBOX.width, puzzleBBOX.height);
                var centerX = puzzleBBOX.x + puzzleBBOX.width / 2;
                var centerY = puzzleBBOX.y + puzzleBBOX.height / 2;
                var cameraHalfSide = bboxBiggestDim / 2;
                centerX += cameraHalfSide * 0;
                centerY += cameraHalfSide * 0;
                var camera = new THREE.OrthographicCamera(centerX - cameraHalfSide, centerX + cameraHalfSide,
                        centerY - cameraHalfSide, centerY + cameraHalfSide, 0, hyp(puzzleBBOX.width, puzzleBBOX.height) / 2);
                camera.up = new THREE.Vector3(0, 1, 0);
                camera.position.x = centerX;
                camera.position.y = centerY;
                camera.position.z = 10;
                camera.lookAt(camera.position.clone().setZ(0));
                camera.updateProjectionMatrix();

                var workFile = [];

                function sliceRendering(pass, renderer, target, inputTexture) {
                    var useScreen = !target || target.renderToScreen;
                    var w = useScreen ? renderer.getSize().width : target.width;
                    var h = useScreen ? renderer.getSize().height : target.height;
                    var slices = 50;
                    var hHeight = Math.floor(h / slices);

                    function createWork(index) {
                        return function () {
                            //console.log(0, index * hHeight, w, hHeight);
                            renderer.enableScissorTest(true);
                            console.log(h, hHeight, index * hHeight, h - index * hHeight);
                            renderer.setScissor(0, index * hHeight, w, Math.min(hHeight, h - index * hHeight));
                            pass.render(renderer, target, inputTexture);
                            renderer.enableScissorTest(false);
                            graphRenderer.context.getError();
                        }
                    }

                    for (var i = 0; i * hHeight < h; i++) {
                        workFile.push(createWork(i));
                    }
                }

                function render(textureData) {
                    textureData.push(textureData[0], textureData[1]);
                    var pointCount = textureData.length / 2;
                    console.log('pointCount', pointCount);
                    var pointsTexture = new THREE.DataTexture(new Float32Array(textureData), pointCount, 1,
                            THREE.LuminanceAlphaFormat, THREE.FloatType, THREE.Texture.DEFAULT_MAPPING,
                            THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter,
                            THREE.NearestFilter);

                    pointsTexture.generateMipmaps = false;
                    pointsTexture.needsUpdate = true;
                    distancePass.material.defines.pointCount = pointCount;
                    distancePass.material.uniforms.projectionMatrix2.value = camera.projectionMatrix;
                    distancePass.material.uniforms.viewMatrix2.value = camera.matrixWorldInverse;
                    distancePass.material.uniforms.distanceScale.value = 1.0;
                    // distancePass.material.uniforms.textureScale.value = maxTexture;
                    distancePass.renderToScreen = false;
                    distancePass.material.needsUpdate = true;
                    distancePass.clear = true;
                    sliceRendering(distancePass, graphRenderer, depthRT, pointsTexture);

                    medialAxisPass.material.uniforms.gridSize.value.setX(depthRT.width);
                    medialAxisPass.material.uniforms.gridSize.value.setY(depthRT.height);
                    medialAxisPass.material.needsUpdate = true;
                    medialAxisPass.renderToScreen = false;
                    medialAxisPass.clear = true;
                    sliceRendering(medialAxisPass, graphRenderer, depthRT2, depthRT.texture);

                    console.log(graphRenderer.context.getError());
                    console.log('borderPass');
                    borderPass.material.defines.pointCount = pointCount;
                    borderPass.material.uniforms.projectionMatrix2.value = camera.projectionMatrix;
                    borderPass.material.uniforms.viewMatrix2.value = camera.matrixWorldInverse;
                    borderPass.renderToScreen = true;
                    borderPass.material.needsUpdate = true;
                    borderPass.clear = true;
                    sliceRendering(borderPass, graphRenderer, null, pointsTexture);
                    console.log('reconstructionPass');
                    reconstructionPass.material.defines.gridX = depthRT2.width;
                    reconstructionPass.material.defines.gridY = depthRT2.height;
                    reconstructionPass.material.needsUpdate = true;
                    reconstructionPass.renderToScreen = true;
                    reconstructionPass.clear = false;
                    sliceRendering(reconstructionPass, graphRenderer, null, depthRT2.texture);
                    var res = new Float32Array([12, 12, 12, 12]);
                    console.log(res);
                    /*
                     console.log('medial axis');
                     medialAxisPass.material.uniforms.gridSize.value.setX(depthRT.width);
                     medialAxisPass.material.uniforms.gridSize.value.setY(depthRT.height);
                     medialAxisPass.material.needsUpdate = true;
                     medialAxisPass.renderToScreen = true;
                     medialAxisPass.clear = false;
                     sliceRendering(medialAxisPass, graphRenderer, null, depthRT.texture);
                     */
                    function doWork() {
                        if (!workFile.length) {
                            console.log('done!');
                            return;
                        }
                        var work = workFile.shift();
                        work();
                        graphRenderer.readRenderTargetPixels(depthRT2, 0, 0, 1, 1, res);
                        setTimeout(doWork, 100);
                    }

                    setTimeout(doWork, 100);

                }

                var textureData = [];
                $.each(points, function (i, point) {
                    textureData.push(point.x, point.y);
                });
                render(textureData);
            });
</script>
</body>
</html>